#include "sim900a.h"

#include <QTextCodec>

extern "C"{
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <termios.h>
#include <sys/types.h>
#include <sys/select.h>
#include <stdlib.h>
#include <unistd.h>
#include <netdb.h>
#include <string.h>
#include <errno.h>
#include <time.h>
}



QString toUniCode(string data)
{
    QString strout;
    QTextCodec *codec = QTextCodec::codecForName("UTF8");
    QString unidata = codec->toUnicode(data.c_str());
    for (int i=0; i<unidata.length(); ++i)
    {
        ushort num = unidata[i].unicode();
        if (num < 255)
            strout += "00";

        strout += QString::number(num,16);
    }
    return strout.toUpper();
}

static struct timeval timeout;
#define DEV_PATH   "/dev/ttySAC0"//ttySAC2

/* 设置窗口参数，读卡器:115200速率 */
static void init_tty(int fd)
{
    //声明设置串口的结构体
    struct termios termios_new;
    //先清空该结构体
    bzero( &termios_new, sizeof(termios_new));
    //	cfmakeraw()设置终端属性，就是设置termios结构中的各个参数。
    cfmakeraw(&termios_new);
    //设置波特率
    //termios_new.c_cflag=(B9600);
    cfsetispeed(&termios_new, B115200);
    cfsetospeed(&termios_new, B115200);
    //CLOCAL和CREAD分别用于本地连接和接受使能，因此，首先要通过位掩码的方式激活这两个选项。
    termios_new.c_cflag |= CLOCAL | CREAD;
    //通过掩码设置数据位为8位
    termios_new.c_cflag &= ~CSIZE;
    termios_new.c_cflag |= CS8;
    //设置无奇偶校验
    termios_new.c_cflag &= ~PARENB;
    //一位停止位
    termios_new.c_cflag &= ~CSTOPB;
    tcflush(fd,TCIFLUSH);
    // 可设置接收字符和等待时间，无特殊要求可以将其设置为0
    termios_new.c_cc[VTIME] = 1;
    termios_new.c_cc[VMIN] = 1;
    // 用于清空输入/输出缓冲区
    tcflush (fd, TCIFLUSH);
    //完成配置后，可以使用以下函数激活串口设置
    if(tcsetattr(fd,TCSANOW,&termios_new) )
        printf("Setting the serial1 failed!\n");

}

//  AT+CMGF=1  //选择发送短信模式
int modeRequest(int fd)
{
    char RBuf[128];
    int ret, i;
    fd_set rdfd;
    memset(RBuf, 0, 128);

    string data = "AT+CMGF=1\r\n";


    write(fd, data.c_str(), data.size());
    memset(RBuf, 0, sizeof(RBuf));

    sleep(3);
    ret = read(fd, RBuf, 50);
    if (ret < 0)
    {
        QString s;
        welog_debug() << s.sprintf("ret = %d, 0x%x\n", ret, errno);
        return -1;
    }
    QString buf = RBuf;
    welog_debug() << "RBuf = " << buf;
    if (buf.contains("OK"))
    {
        return 0;
    }
    return -1;
    /*
     *
     * FD_ZERO(&rdfd);
    FD_SET(fd,&rdfd);
    timeout.tv_sec = 5;
    timeout.tv_usec = 0;
    ret = select(fd + 1,&rdfd, NULL,NULL,&timeout);
    memset(RBuf, 0, sizeof(RBuf));
    switch(ret)
    {
        case -1:
            perror("select error\n");
            break;
        case  0:
            perror("Timeout:");
            break;
        default:
        {
            ret = read(fd, RBuf, 50);
            if (ret < 0)
            {
                printf("ret = %d, 0x%x\n", ret, errno);
                break;
            }
            QString data = RBuf;
           welog_debug() << "RBuf = " << data;
            if (data.contains("OK"))//(RBuf[0] == 'O' && RBuf[1] == 'K') //应答帧状态部分为0 则获取ID 成功
            {
                return 0;
            }
        }
    }
    return -1;*/
}

//AT+CSCS="UCS2" -中文  //选择TE字符集，设定为GSM
int letterRequest(int fd)
{
    char WBuf[128], RBuf[128] = {0};
    int  ret, i;
    fd_set rdfd;

    string data = "AT+CSCS=\"UCS2\"\r\n";//GSM-英文

    FD_ZERO(&rdfd);
    FD_SET(fd,&rdfd);

    timeout.tv_sec = 5;
    timeout.tv_usec = 0;
    write(fd, data.c_str(), data.size());
    memset(RBuf, 0, sizeof(RBuf));

    ret = read(fd, RBuf, 50);
    if (ret < 0)
    {
        QString s;
        welog_debug() << s.sprintf("ret = %d, 0x%x\n", ret, errno);
        return -1;
    }
    QString buf = (char *)RBuf;
    welog_debug() << "RBuf = " << buf;
    if (buf.contains("OK"))
    {
        // 卡的类型
        return 0;
    }
    return -1;
    /*
    ret = select(fd + 1,&rdfd, NULL,NULL,&timeout);// select什么情况返回-1 ？返回0？返回其它值？
    switch(ret)
    {
        case -1:
            perror("select error\n");
            break;
        case  0:
            welog_debug() << ("Request timed out.");
            break;
        default:
            ret = read(fd, RBuf, 50);
            if (ret < 0)
            {
                printf("ret = %d, 0x%x\n", ret, errno);
                break;
            }

            QString data = (char *)RBuf;
            welog_debug() << "RBuf = " << data;
            if (data.contains("OK"))//(RBuf[0] == 'O' && RBuf[1]=='K')	 	//应答帧状态部分为0 则请求成功
            {
                // 卡的类型
                return 0;
            }
            break;
    }
    return -1;*/
}

int CSMP_request(int fd)
{
    char RBuf[128] = {0};
    string data = "AT+CSMP=17,167,0,25\r\n";
    write(fd, data.c_str(), data.size());
    welog_debug() << "CSMP_request : " << data.c_str();
    memset(RBuf, 0, sizeof(RBuf));
    int ret = read(fd, RBuf, 50);
    if (ret < 0)
    {
        QString s;
        welog_debug() << s.sprintf("ret = %d, 0x%x\n", ret, errno);
        return -1;
    }
    QString buf = (char *)RBuf;
    welog_debug() << "RBuf = " << buf;
    return 0;
}

//发送手机号码
int phoneRequest(int fd, string )
{
    char RBuf[128];
    int ret;
    fd_set rdfd;
    memset(RBuf, 0, 128);

    QString tmp = toUniCode(SIM900A::Get()->phone);
    welog_debug() << "tmp = " << SIM900A::Get()->phone.c_str();
    string phone = "AT+CMGS=\"" + tmp.toStdString() + "\"\r\n";
    welog_debug() << "phone1 = " << phone.c_str();

    FD_ZERO(&rdfd);
    FD_SET(fd,&rdfd);
    write(fd, phone.c_str(), phone.size());
/*
    memset(RBuf, 0, 128);
    ret = read(fd, RBuf, 50);
    if (ret < 0)
    {
        printf("ret = %d, 0x%x\n", ret, errno);
        return -1;
    }
    QString data = RBuf;
    welog_debug() << "RBuf = " << data;

    if (data.contains('>'))
    {
        return 0;
    }*/
    return 0;
    /*
    timeout.tv_sec = 5;
    timeout.tv_usec = 0;
    ret = select(fd + 1,&rdfd, NULL,NULL,&timeout);
    switch(ret)
    {
        case -1:
        {
            perror("select error\n");
            break;
        }
        case  0:
        {
            perror("Timeout:");
            break;
        }
        default:
            ret = read(fd, RBuf, 50);
            if (ret < 0)
            {
                printf("ret = %d, 0x%x\n", ret, errno);
                break;
            }
            QString data = RBuf;
            welog_debug() << "RBuf = " << data;

            if (data.contains('>')) //应答帧状态部分为0 则获取ID 成功
            {
                return 0;
            }
    }
    return -1;*/
}

//发送短信
int sendMsg(int fd)
{
    char RBuf[128];
    int ret, i;
    fd_set rdfd;
    memset(RBuf, 0, 128);

    //string data = "hello";
    QString tmp = toUniCode(SIM900A::Get()->msg);
    welog_debug() << "msg : " << tmp;
    //QString tmp = toUniCode(SIM900A::Get()->msg);
    string data = tmp.toStdString();//tmp.toStdString();

    FD_ZERO(&rdfd);
    FD_SET(fd,&rdfd);
    write(fd, data.c_str(), data.size());
/*
    timeout.tv_sec = 30;
    timeout.tv_usec = 0;
    ret = select(fd + 1,&rdfd, NULL,NULL,&timeout);
    switch(ret)
    {
        case -1:
            perror("select error\n");
            break;
        case  0:
            perror("Timeout:");
            break;
        default:
            ret = read(fd, RBuf, 50);
            if (ret < 0)
            {
                printf("ret = %d, 0x%x\n", ret, errno);
                break;
            }
           welog_debug() << "RBuf = " << RBuf;
            //if (RBuf[0] == '>') //应答帧状态部分为0 则获取ID 成功
            {
                return 0;
            }
    }
*/
    return 0;
}

int ackRequest(int fd)
{
    char RBuf[128];
    int ret;
    fd_set rdfd;
    memset(RBuf, 0, 128);

    unsigned char data = 0x1A;

    FD_ZERO(&rdfd);
    FD_SET(fd,&rdfd);
    write(fd, &data, sizeof(data));

    ret = read(fd, RBuf, 50);
    if (ret < 0)
    {
        printf("ret = %d, 0x%x\n", ret, errno);
        return -1;
    }
    QString buf = RBuf;
    welog_debug() << "RBuf = " << buf;
    //if (buf.contains("OK")) //应答帧状态部分为0 则获取ID 成功
    {
        return 0;
    }
    /*
    timeout.tv_sec = 60;
    timeout.tv_usec = 0;
    ret = select(fd + 1,&rdfd, NULL,NULL,&timeout);
    switch(ret)
    {
        case -1:
            perror("select error\n");
            break;
        case  0:
            perror("Timeout:");
            break;
        default:
            ret = read(fd, RBuf, 50);
            if (ret < 0)
            {
                printf("ret = %d, 0x%x\n", ret, errno);
                break;
            }
            QString data = RBuf;
            welog_debug() << "RBuf = " << data;
            if (data.contains("OK")) //应答帧状态部分为0 则获取ID 成功
            {
                return 0;
            }
    }


    return 0;*/
}

SIM900A::SIM900A()
{

}

void SIM900A::run()
{
#ifdef SUPPORT_ARM
    int fd;

    fd = open(DEV_PATH, O_RDWR | O_NOCTTY | O_NONBLOCK);//非阻塞,发送完命令后即使没有卡回应，也不会阻塞
    if (fd < 0)
    {
        fprintf(stderr, "Open GEC6818_ttySAC1 fail!\n");
        return ;
    }
    /*初始化串口*/
    init_tty(fd);
    timeout.tv_sec = 1;
    timeout.tv_usec = 0;

    sleep(3);
    modeRequest(fd);
    //while ( != 0)
    //{
    //    sleep(3);
    //}

    sleep(3);
    letterRequest(fd);
    //while (letterRequest(fd) != 0)
    {
        //sleep(3);
    }
    sleep(3);

    CSMP_request(fd);
    //sleep(3);

    mode = 4;
    while(1)
    {
        switch (mode)
        {
            case 0:
            {
                welog_debug() << "phoneRequest";
                phoneRequest(fd, "17179654393");
                mode = 1;
                break;
            }
            case 1:
            {
                welog_debug() << "sendMsg";
                sendMsg(fd);
                mode = 2;
            }
            case 2:
            {
                welog_debug() << "ackRequest";
                mode = 4;
                ackRequest(fd);
                break;
            }
            default:
                break;
        }
        sleep(3);
    }
    close(fd);

#endif
/*
#if 0
    QString description;
    QString manufacturer;
    QString serialNumber;
    QString portName;
    const auto infos = QSerialPortInfo::availablePorts();
    for (const QSerialPortInfo &info : infos)
    {
        QStringList list;
        description = info.description();//串口描述
        manufacturer = info.manufacturer();//串口设备制造商
        serialNumber = info.serialNumber();//串口序列号
        portName = info.portName();//串口描述
    }
    welog_debug() << "name = " << portName;

    bool ret = false;
    if(!portName.isEmpty())
    {
        serial = new QSerialPort;
        //this->serial = &serial;
        serial->setPortName(portName);
        serial->setBaudRate(QSerialPort::Baud115200);
        serial->setDataBits(QSerialPort::Data8);
        serial->setParity(QSerialPort::NoParity);
        serial->setStopBits(QSerialPort::OneStop);
        serial->setFlowControl(QSerialPort::NoFlowControl);
        if(serial->open(QIODevice::ReadWrite))
        {
            welog_debug() << "open ok";
            QString data = writeDate("AT+CSCS=\"GSM\"\r\n");
            if(!data.isEmpty())
            {
               data = writeDate("AT+CMGF=1" + END);
               if(!data.isEmpty())
               {
                    data = writeDate("AT+CMGS=\"17179654393\"" + END);
                    if(!data.isEmpty())
                    {
                        data = writeDate("hello");
                        if(!data.isEmpty())
                        {
                            int end = 0x1A;
                            serial->write((char *)end, sizeof(end));
                            serial->waitForReadyRead(30*1000);
                            welog_debug() << serial->readAll();
                        }
                        else
                            welog_debug() << "time out000";
                    }
                    else
                        welog_debug() << "time out111";
               }
               else
                   welog_debug() << "time out222";
            }
            else
                welog_debug() << "time out333";
            serial->close();
        }
        else
        {
            welog_debug() << "open fail";
        }
    }
#endif*/
}

QString SIM900A::writeDate(string data)
{
    QString buf = "";
    bool ret;
    welog_debug() << "send : " << serial->write(data.c_str(), data.size());
    ret = serial->waitForReadyRead(5000);
    if(ret)
    {
        buf = serial->readAll();
        welog_debug() << "buf : " << buf;
    }
    return buf;
}

void SIM900A::setUser(QString phone, QString msg)
{
    welog_debug() << "phone ： " << phone;
    this->phone = phone.toStdString();
    this->msg = msg.toStdString();
    mode = 0;
}
